package com.woniuxy.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.woniuxy.controller.form.CreateTopicForm;
import com.woniuxy.controller.form.TopicPageFrom;
import com.woniuxy.controller.form.VoteAnswerFomr;
import com.woniuxy.controller.info.PageTopicInfo;
import com.woniuxy.controller.info.Result;
import com.woniuxy.dao.TopicDao;
import com.woniuxy.model.Answer;
import com.woniuxy.dao.AnswerDao;
import com.woniuxy.model.Topic;
import com.woniuxy.service.AnswerService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniuxy.util.ObjectRedisTemplate;
import com.woniuxy.util.WoniuCopyUtil;
import com.woniuxy.util.exception.AlreagyVoteException;
import com.woniuxy.util.exception.PersonalException;
import com.woniuxy.util.exception.TopicAlradyException;
import com.woniuxy.util.exception.code.AnswerExceptionCode;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author Kevin Martin
 * @since 2022-03-19
 */
@Service
public class AnswerServiceImpl extends ServiceImpl<AnswerDao, Answer> implements AnswerService {
    @Resource
    private TopicDao topicDao;
    @Resource
    private ObjectRedisTemplate objectRedisTemplate;

    @Override
    public Result<?> creatTopic(CreateTopicForm createTopicForm) throws TimeoutException {
        Topic entity = WoniuCopyUtil.copyOne(createTopicForm, Topic.class);
        topicDao.insert(entity);
        List<Answer> entityList = WoniuCopyUtil.copyMany(createTopicForm.getAnswers(), Answer.class);
//        boolean b = saveBatch(entityList);

        QueryWrapper<Topic> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("topic_accountid",createTopicForm.getTopicAccountid()).eq("topic_content",createTopicForm.getTopicContent());
        Topic topic = null;
        try {
            topic = topicDao.selectOne(queryWrapper);
        } catch (Exception e) {
            throw new TopicAlradyException(AnswerExceptionCode.AnswerExit_EXCEPTION_CODE);
        }
        for (Answer answer : entityList) {
            answer.setTopicId(topic.getTopicId());
        }
        saveBatch(entityList);
//        List<Answer> answerslist = list(queryWrapper);

        long time1 = new Date().getTime();
        Long topicEndTime = createTopicForm.getTopicEndTime();
        long time = -(time1 - topicEndTime)/1000;
        System.out.println(time1+"-"+topicEndTime+"="+time);
        if(time<=0){
            throw new TimeoutException("时间超时");
        }
//        objectRedisTemplate.opsForZSet()
        //添加话题
        objectRedisTemplate.opsForList().leftPush("topic",entity);
        objectRedisTemplate.expire("topic",time, TimeUnit.SECONDS);
        //添加答案
        for (Answer answer : entityList) {
            objectRedisTemplate.opsForZSet().addIfAbsent("topic:Id:"+entity.getTopicId()+"answers:",answer,0);
            objectRedisTemplate.expire("topic:Id:"+entity.getTopicId()+"answers:",time, TimeUnit.SECONDS);
        }
        return Result.getInstance().setMsg("添加话题成功");
    }

    @Override

    public Result<IPage<PageTopicInfo>> getTopicAndAnswer(TopicPageFrom topicPageFrom) {
        //获取对应页数的话题
        Long pageTotal = objectRedisTemplate.opsForList().size("topic");
        Long pagePages= pageTotal /topicPageFrom.getPageSize();
        List<Object> topic = objectRedisTemplate.opsForList().range("topic",
                (topicPageFrom.getPageIndex() - 1) * topicPageFrom.getPageSize(), topicPageFrom.getPageIndex() * topicPageFrom.getPageSize() - 1);
        List<PageTopicInfo> pageTopicInfos = WoniuCopyUtil.copyMany(topic, PageTopicInfo.class);
        if(null==pageTopicInfos||0==pageTopicInfos.size()){
            //数据库获取
//            List<Topic> topics = topicDao.selectList(null);
            Page<Topic> topicPage = topicDao.selectPage(new Page<Topic>(topicPageFrom.getPageIndex(), topicPageFrom.getPageSize()), null);
//            pageTopicInfos = WoniuCopyUtil.copyMany(topics, PageTopicInfo.class);
            pageTopicInfos=WoniuCopyUtil.copyMany(topicPage.getRecords(), PageTopicInfo.class);
            pagePages=topicPage.getPages();
            pageTotal=topicPage.getTotal();
        }

        System.out.println("+++++++++++++++++++++"+pageTopicInfos);
        for (PageTopicInfo pageTopicInfo : pageTopicInfos) {
            Set<ZSetOperations.TypedTuple<Object>> typedTuples = objectRedisTemplate.opsForZSet().rangeWithScores("topic:Id:" + pageTopicInfo.getTopicId() + "answers:", 0, -1);
            pageTopicInfo.setAnswers(typedTuples);
            if(null==typedTuples){
                //mysql中查询 不会
                throw new PersonalException("redis中的数据没有了 sql 查询set集合 臣做不到呀",9958);
            }
        }

        IPage<PageTopicInfo> simpleAccountnfoIPage = new Page<PageTopicInfo>().setPages(pagePages)
                                                                                .setSize(topicPageFrom.getPageSize())
                                                                                .setCurrent(topicPageFrom.getPageIndex())
                                                                                .setTotal(pageTotal)
                                                                                .setRecords(pageTopicInfos);
        return Result.getInstance(IPage.class).setData(simpleAccountnfoIPage);



    }

    @Override
    public Result voteAnswer(VoteAnswerFomr voteAnswerFomr) {
        List<Object> range = objectRedisTemplate.opsForList().range("topic:Id:" + voteAnswerFomr.getTopicId() + "answers:voteId", 0, -1);
        System.out.println(range);
        if(range!=null&&range.size()!=0 ){

            for (Object integer : range) {
                if((Integer) integer==voteAnswerFomr.getAccountId()){
                    throw new AlreagyVoteException(AnswerExceptionCode.ALARDYVOTE_EXCEPTION_CODE);
                }
            }
        }
        objectRedisTemplate.opsForList().leftPush("topic:Id:" + voteAnswerFomr.getTopicId() + "answers:voteId",voteAnswerFomr.getAccountId());
        Double aDouble = objectRedisTemplate.opsForZSet().incrementScore("topic:Id:" + voteAnswerFomr.getTopicId() + "answers:", voteAnswerFomr.getAnswer(), 1);
        System.out.println(aDouble);
        return Result.getInstance().setMsg("成功");
    }
}
